﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;

namespace Pavilion
{
    public delegate void PositionChangedHandler(PhysicalData physicalData, float xDistance, float yDistance);
    public class PhysicalData : IPropertyChanged
    {
        public event PositionChangedHandler PositionChanged;
        public event Action<PhysicalData> PhysicalFormChanged;
        public event PropertyChangedHandler PropertyChanged;
        public event Action<PhysicalData> IsFlippedHorizontallyChanged;

        private Vector2 position, speedCalculations;
        private float speedX, speedY, size;
        private bool isFlippedHorizontally;
        private PhysicalState physicalState;
        private Momentum momentum = Momentum.None;

        public PhysicalState PhysicalState { get { return physicalState; } set { physicalState = value; OnPropertyChanged("PhysicalState"); } }
        public Momentum Momentum { get { return momentum; } set { momentum = value; OnPropertyChanged("Momentum"); } }

        public Vector2 Position { get { return position; } }
        public float Size { get { return size; } set { size = value; OnPhysicalFormChanged(); } }
        public bool IsFlippedHorizontally
        {
            get { return isFlippedHorizontally; }
            set { isFlippedHorizontally = value; UpdateSpeedXCalculations(); OnIsFlippedHorizontallyChanged(); }
        }
        public float SpeedX
        {
            get { return speedX; }
            set { speedX = value; UpdateSpeedXCalculations(); OnPropertyChanged("SpeedX"); }
        }
        public float SpeedY
        {
            get { return speedY; }
            set { speedY = value; speedCalculations.Y = speedY * Size * ((float)AnimationPlayer.FramesPerSecond / 12f) * 3; OnPropertyChanged("SpeedY"); }
        }

        public virtual void Move(float xDistance, float yDistance)
        {
            SetPosition(Position.X + xDistance, Position.Y + yDistance);
        }

        public void MoveBySpeed()
        {
            Move(speedCalculations.X, speedCalculations.Y);
        }

        public virtual void SetPosition(float x, float y)
        {
            if (position.X == x && position.Y == y)
                return;

            float xDistance = x - position.X;
            float yDistance = y - position.Y;

            this.position.X = x;
            this.position.Y = y;

            OnPositionChanged(xDistance, yDistance);
        }

        private void UpdateSpeedXCalculations()
        {
            if (IsFlippedHorizontally)
                speedCalculations.X = speedX * Size * ((float)AnimationPlayer.FramesPerSecond / 12f) * -3;
            else
                speedCalculations.X = speedX * Size * ((float)AnimationPlayer.FramesPerSecond / 12f) * 3;
        }

        protected void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, propertyName);
        }

        protected void OnPhysicalFormChanged()
        {
            if (PhysicalFormChanged != null)
                PhysicalFormChanged(this);
        }

        private void OnPositionChanged(float xDistance, float yDistance)
        {
            if (PositionChanged != null)
                PositionChanged(this, xDistance, yDistance);
        }

        private void OnIsFlippedHorizontallyChanged()
        {
            if (IsFlippedHorizontallyChanged != null)
                IsFlippedHorizontallyChanged(this);

            OnPhysicalFormChanged();
            OnPropertyChanged("IsFlippedHorizontally");
        }
    }

    public enum Momentum
    {
        Forward,
        Backward,
        None,
    }

    public enum PhysicalState
    {
        Grounded,
        Rising,
        Falling,
        Sinking,
        Floating
    }
}
